<template>
  <div class="page-box">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>Contract</span>
          <el-link type="primary" href="https://remix.ethereum.org/" target="_blank">Remix</el-link>
        </div>
      </template>
      <div class="card-content">
        <el-row :gutter="20">
          <el-col :lg="12" :sm="24">
            <div class="item">
              <p class="title">
                1. 编写TODO.
                <f-code :code="code" />
              </p>
            </div>
            <div class="item">
              <p class="title">2. 部署合约</p>
              <el-alert type="success" :closable="false">
                <span>Contract Address: </span>
                <el-link
                  type="primary"
                  :href="`https://goerli.etherscan.io/address/${todoAddress}`"
                  target="_blank"
                  >{{ todoAddress }}</el-link
                ><br />
              </el-alert>
            </div>
            <div class="item">
              <p class="title">3. 获取合约ABI</p>
              <f-code :code="todoAbi" />
            </div>
          </el-col>
          <el-col :lg="12" :sm="24" class="opt">
            <div class="item">
              <p class="title" style="font-weight: bold">合约交互</p>
              <el-button type="primary" @click="getTotalTodo">查询Total</el-button>
              <el-alert type="success" :closable="false" v-if="totalTodo > 0">
                <span>总共有: </span><span>{{ totalTodo }}</span> 个待办<br />
              </el-alert>
            </div>
            <div class="item">
              <div>
                <el-input-number v-model="indexTodo" controls-position="right" :min="1" :step="1" />
                <el-button type="primary" @click="getTodoInfo" class="ml8">查询指定TODO</el-button>
              </div>
              <el-alert type="success" :closable="false" v-if="todoInfo.text != ''">
                <span>描述: </span> <span>{{ todoInfo.text }}</span> <br />
                <span>是否完成: </span> <span>{{ todoInfo.completed }}</span> <br />
              </el-alert>
            </div>
            <div class="item">
              <div class="flex">
                <el-input v-model="todoText" placeholder="Please input text" />
                <el-button type="primary" @click="createTodo" class="ml8">创建TODO</el-button>
              </div>
              <el-alert type="success" :closable="false" v-if="createHash != ''">
                <span>Tx Hash: </span>
                <el-link
                  type="primary"
                  :href="`https://goerli.etherscan.io/tx/${createHash}`"
                  target="_blank"
                  >{{ createHash }}</el-link
                ><br />
              </el-alert>
            </div>
            <div class="item">
              <div>
                <el-input-number
                  v-model="indexCompleted"
                  controls-position="right"
                  :min="1"
                  :step="1"
                />
                <el-button type="primary" @click="handleCompleted" class="ml8">完成TODO</el-button>
              </div>
              <el-alert type="success" :closable="false" v-if="createHash != ''">
                <span>Tx Hash: </span>
                <el-link
                  type="primary"
                  :href="`https://goerli.etherscan.io/tx/${completeHash}`"
                  target="_blank"
                  >{{ completeHash }}</el-link
                ><br />
              </el-alert>
            </div>
          </el-col>
        </el-row>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, toRaw } from 'vue'
import FCode from '@/components/f-code/index.vue'
import { contract_code, contract_address, contract_abi } from '@/hooks/contract'
import { useConnectorStore } from '@/stores/connector'
import { storeToRefs } from 'pinia'
import { ElMessage, ElNotification } from 'element-plus'
import { useRouter } from 'vue-router'

const router = useRouter()
const code = ref(contract_code)
const todoAddress = ref(contract_address)
const todoAbi = ref(`${JSON.stringify(contract_abi, null, 4)}`)

const connectorStore = useConnectorStore()
const connect = toRaw(connectorStore.connect)
const { account } = storeToRefs(connectorStore)

// 总数
const totalTodo = ref(0)
const getTotalTodo = async () => {
  const [err, res] = await call('total')
  if (err) return
  totalTodo.value = res.toNumber()
}
// 获取指定index的todo信息
const indexTodo = ref(0)
const todoInfo = ref({
  text: '',
  completed: false,
})
const getTodoInfo = async () => {
  if (indexTodo.value === null || isNaN(Number(indexTodo.value))) return
  const [err, res] = await call('get', indexTodo.value - 1)
  if (err) return
  todoInfo.value.text = res[0]
  todoInfo.value.completed = res[1]
}

// 完成todo
const indexCompleted = ref(0)
const completeHash = ref('')
const handleCompleted = async () => {
  if (indexCompleted.value === null || isNaN(Number(indexCompleted.value))) return
  const [err, res] = await sendTx('completed', indexCompleted.value - 1)
  if (err) return
  completeHash.value = res.hash
  await connect.provider?.waitForTransaction(res.hash)
  ElMessage({
    message: 'Success',
    type: 'success',
  })
}

// 创建todo
const todoText = ref('')
const createHash = ref('')
const createTodo = async () => {
  if (todoText.value === '') return
  const [err, res] = await sendTx('create', todoText.value)
  if (err) return
  createHash.value = res.hash
  ElMessage({
    message: 'Success',
    type: 'success',
  })
  await connect.provider?.waitForTransaction(res.hash)
  ElNotification({
    title: 'Success',
    dangerouslyUseHTMLString: true,
    showClose: false,
    message: `<div>创建成功,查看交易详情: <span style="color:var(--el-color-primary);cursor: pointer;">${res.hash.substring(
      0,
      7,
    )}...</span></div>`,
    duration: 3000,
    onClick: () => {
      router.push({ path: `/transactionInfo/${res.hash}` })
    },
  })
}

// 封装查询call
const call = async (name: string, ...args: any): Promise<[any, any]> => {
  try {
    const contract = connect.contractCall(contract_address, contract_abi)
    const res = await contract[`${name}`](...args)
    return Promise.resolve([null, res])
  } catch (error: any) {
    ElNotification({
      title: 'Warning',
      message: error.reason || 'execution reverted',
      type: 'warning',
    })
    return Promise.resolve([error, null])
  }
}

// 封装发送交易
const sendTx = async (name: string, ...args: any): Promise<[any, any]> => {
  if (account.value === '') {
    ElNotification({
      title: 'Warning',
      message: '请先连接钱包！',
      type: 'warning',
    })
    return Promise.resolve([true, null])
  }
  try {
    const contract = connect.contractTx(contract_address, contract_abi)
    const gasLimit = await contract.estimateGas[`${name}`](...args) // 预估gas
    const res = await contract[`${name}`](...args, {
      gasLimit: gasLimit.mul(150).div(100), // 放大1.5倍gas，增加交易成功率
    })
    return Promise.resolve([null, res])
  } catch (error: any) {
    ElNotification({
      title: 'Warning',
      message: error.reason || 'execution reverted',
      type: 'warning',
    })
    return Promise.resolve([error, null])
  }
}
</script>

<style scoped lang="less">
.opt {
  .item {
    min-height: 120px;
  }
}
.item {
  .flex {
    display: flex;
  }
  .ml8 {
    margin-left: 8px;
  }
}
</style>
